package  
{
	import org.flixel.*;
	import org.flixel.FlxGroup;
	
	public class Background extends FlxGroup
	{
		private var _time:Number;
		private var _background:FlxSprite;
		private var _sunAndStars:FlxSprite;
		private var _left:Array;
		private var _right:Array;
		private var _cities:Array;
		
		private var _timeFactor:Number = 1;
		private var _alpha:Number = 1;
		
		private var _timesToColors:Array = [
			[0.0, 0x82BCE1, 0xBFE6FF],
			[0.07, 0x44C5FC, 0xEAF5F9],
			[0.14, 0x15B1FA, 0xF9F9F9],
			[0.26, 0x60A0FF, 0xFFFFFF],
			[0.30, 0xCEB5D0, 0xE2C9E5],
			[0.35, 0xFBAB8C, 0xF9BBA4],
			[0.42, 0xF58E6E, 0xFFA88E],
			[0.49, 0x4D5172, 0x7076A5],
			[0.56, 0x2E306A, 0x949AEF],
			[0.63, 0x011E2B, 0x97AAC6],
			[0.7, 0x32305E, 0x8280B5],
			[0.77, 0x524E7D, 0x8983D3],
			[0.9, 0xFA89D8, 0xF9A9E1],
			[0.95, 0xEDA831, 0xEACA96],
			];
		
		private var _camera:FlxCamera;
		
		private function addBackground(graphic:Class, x:int, y:int, scroll:Number, alpha:Number = 1):void
		{
			var left:FlxSprite = new FlxSprite(x, y, graphic);
			left.alpha = alpha;
			left.scrollFactor = new FlxPoint(scroll, scroll);
			this.add(left);
			_left.push(left);
			
			var right:FlxSprite = new FlxSprite(left.x + left.width, y, graphic);
			right.alpha = alpha;
			right.scrollFactor = new FlxPoint(scroll, scroll);
			this.add(right);
			_right.push(right);
		}
		
		private function addBackgrounds(graphicA:Class, graphicB:Class, x:int, y:int, scroll:Number):void
		{
			var left:FlxSprite = new FlxSprite(x, y, graphicA);
			left.scrollFactor = new FlxPoint(scroll, scroll);
			this.add(left);
			_left.push(left);
			
			var right:FlxSprite = new FlxSprite(left.x + left.width, y, graphicB);
			right.scrollFactor = new FlxPoint(scroll, scroll);
			this.add(right);
			_right.push(right);
		}
		
		private function addCity(graphic:Class, x:int, y:int, scroll:Number):void
		{
			var city:FlxSprite = new FlxSprite(x, y, graphic);
			city.scrollFactor = new FlxPoint(scroll, scroll);
			this.add(city);
			_cities.push(city);
		}
		
		public function Background(camera:FlxCamera):void
		{
			_time = 0;
			_camera = camera;
			_left = new Array();
			_right = new Array();
			_cities = new Array();
			
			_background = new FlxSprite();
			_background.makeGraphic(FlxG.width, FlxG.height, 0xFFFFFFFF);
			_background.scrollFactor = new FlxPoint(0, 0);
			this.add(_background);
			
			_sunAndStars = new FlxSprite(0, 0, AssetManager.SunAndStars);
			_sunAndStars.x = -_sunAndStars.width / 2;
			_sunAndStars.y = FlxG.height - _sunAndStars.height / 2;
			_sunAndStars.scrollFactor = new FlxPoint(0, 0);
			this.add(_sunAndStars);
			_sunAndStars.angularVelocity = -(360)/ConfigData.SECONDS_PER_DAY;
			
			addBackground(AssetManager.Mountains, 0, 110 - ConfigData.GROUND_HEIGHT, .4);
			addBackground(AssetManager.Hills, 0, 166 - ConfigData.GROUND_HEIGHT, .5);
			addBackground(AssetManager.FrontFog, 0, 190 - ConfigData.GROUND_HEIGHT, .6, .8);
			var cityX:int = -100;
			var cityY:int = 136 - ConfigData.GROUND_HEIGHT;
			var cityScroll:Number = .6;
			addCity(AssetManager.Civilization1, cityX, cityY, cityScroll);
			cityX += 590;
			addCity(AssetManager.Civilization2, cityX, cityY, cityScroll);
			cityX += 590;
			addCity(AssetManager.Civilization3, cityX, cityY, cityScroll);
			cityX += 590;
			addCity(AssetManager.Civilization4, cityX, cityY, cityScroll);
			cityX += 590;
			addCity(AssetManager.Civilization5, cityX, cityY, cityScroll);
			addBackground(AssetManager.FrontFog, 0, 200 - ConfigData.GROUND_HEIGHT, .7, .6);
			
			addBackground(AssetManager.FrontHills, 0, 240-34 - ConfigData.GROUND_HEIGHT, .8);
		}
		private function lerpColors(a:int, b:int, percent:Number):int
		{
			var aR:int = (a & 0x00FF0000) >> 16;
			var bR:int = (b & 0x00FF0000) >> 16;
			var r:int = aR + (bR - aR) * percent;
			
			var aG:int = (a & 0x0000FF00) >> 8;
			var bG:int = (b & 0x0000FF00) >> 8;
			var g:int = aG + (bG - aG) * percent;
			
			var aB:int = (a & 0x000000FF);
			var bB:int = (b & 0x000000FF);
			var b:int = aB + (bB - aB) * percent;
			var rS:int = r << 16;
			var gS:int = g << 8;
			var bS:int = b;
			var color:int = rS + gS + bS + 0xFF000000;
			return color;
		}
		
		public function get timeFactor():Number
		{
			return _timeFactor;
		}
		
		public function set timeFactor(factor:Number):void
		{
			_timeFactor = factor;
			_sunAndStars.angularVelocity = -(360)/ConfigData.SECONDS_PER_DAY * _timeFactor;
		}
		
		public function set alpha(alpha:Number):void
		{
			_alpha = alpha;
			_background.alpha = _alpha;
			_sunAndStars.alpha = _alpha;
			for (var i:int = 0; i < _left.length; i++)
			{
				var left:FlxSprite = _left[i];
				var right:FlxSprite = _right[i];
				left.alpha = _alpha;
				right.alpha = _alpha;
			}
			for (var c:int = 0; c < _cities.length; c++)
			{
				var city:FlxSprite = _cities[c];
				city.alpha = _alpha;
			}
		}
		
		public function get alpha():Number
		{
			return _alpha;
		}
		
		private function updateBasedOnTime():void
		{
			var lower:int = 0;
			var upper:int = 0;
			var distance:Number = 0;
			for (var i:int = 0; i < _timesToColors.length; i++)
			{
				lower = i;
				upper = (i + 1) % _timesToColors.length;
				var lowTime:Number = _timesToColors[lower][0];
				var highTime:Number = _timesToColors[upper][0];
				if (highTime < lowTime)
				{
					highTime = 1.0;
				}
				if (highTime >= _time)
				{
					distance = (_time - lowTime) / (highTime - lowTime);
					break;
				}
			}
			var lowColor:int = _timesToColors[lower][1];
			var highColor:int = _timesToColors[upper][1];
			var color:int = lerpColors(lowColor, highColor, distance);
			_background.color = color;
			
			var lowTint:int = _timesToColors[lower][2];
			var highTint:int = _timesToColors[upper][2];
			var tint:int = lerpColors(lowTint, highTint, distance);
			for (var j:int = 0; j < _left.length; j++)
			{
				_left[j].color = tint;
				_right[j].color = tint;
			}
			for (var c:int = 0; c < _cities.length; c++)
			{
				var city:FlxSprite = _cities[c];
				city.color = tint;
			}
		}
		
		private function checkAndMoveSprites():void
		{
			for (var i:int = 0; i < _left.length; i++)
			{
				var left:FlxSprite = _left[i];
				var right:FlxSprite = _right[i];
				var leftPoint:FlxPoint = left.getScreenXY(null, _camera);
				var rightPoint:FlxPoint = right.getScreenXY(null, _camera);
				if (leftPoint.x > -20)
				{
					//trace("Moving right to the left: "+leftPoint.x);
					// move right to be left
					right.x = left.x - right.width;
					_right[i] = left;
					_left[i] = right;
				}
				else if (rightPoint.x + right.width < FlxG.width + 20)
				{
					//trace("Moving left to the right: "+rightPoint.x);
					// move left to be right
					left.x = right.x + right.width;
					_left[i] = right;
					_right[i] = left;
				}
			}
			var cityCount:int = _cities.length;
			var leftC:FlxSprite = _cities[0];
			var rightC:FlxSprite = _cities[cityCount-1];
			var leftCPoint:FlxPoint = leftC.getScreenXY(null, _camera);
			var rightCPoint:FlxPoint = rightC.getScreenXY(null, _camera);
			if (leftCPoint.x > -20)
			{
				//trace("Moving right to the left: "+leftPoint.x);
				// move right to be left
				rightC.x = leftC.x - right.width;
				for (var l:int = cityCount = 1; l >= 1; l--)
				{
					_cities[l] = _cities[l - 1];
				}
				_cities[0] = rightC;
			}
			else if (rightCPoint.x + rightC.width < FlxG.width + 20)
			{
				//trace("Moving left to the right: "+rightPoint.x);
				// move left to be right
				leftC.x = rightC.x + rightC.width;
				for (var r:int = 0; r<cityCount-1; r++)
				{
					_cities[r] = _cities[r + 1];
				}
				_cities[cityCount-1] = leftC;
			}
		}
		
		public override function update():void
		{
			_time += (FlxG.elapsed / ConfigData.SECONDS_PER_DAY) * _timeFactor;
			if (_time > 1)
			{
				_time = _time - 1;
			}
			checkAndMoveSprites();
			updateBasedOnTime();
			super.update();
		}
	}

}